package com.yizisu.library.login.impl

import android.app.Activity
import android.content.Intent
import android.content.IntentSender
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.LifecycleOwner
import com.google.android.gms.auth.api.identity.BeginSignInRequest
import com.google.android.gms.auth.api.identity.Identity
import com.google.android.gms.auth.api.identity.SignInClient
import com.google.android.gms.auth.api.identity.SignInCredential
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.common.api.CommonStatusCodes
import com.yizisu.library.login.BaseGameLogin
import com.yizisu.library.login.IGameLogin
import com.yizisu.login.R
import java.lang.IllegalArgumentException

internal class GameLoginOneTapImpl(manager: FragmentManager, lifecycleOwner: LifecycleOwner) :
    BaseGameLogin(manager, lifecycleOwner) {
    companion object {
        private const val REQ_ONE_TAP = 6321
        private fun toUserInfo(account: SignInCredential): IGameLogin.UserInfo {
            val personName = account.displayName
            val personGivenName = account.givenName
            val personFamilyName = account.familyName
            val personEmail = account.id
            val personId = account.id
            val personPhoto = account.profilePictureUri?.toString()
            return IGameLogin.UserInfo(
                account.id,
                account.googleIdToken!!,
                IGameLogin.LOGIN_GOOGLE,
                personName,
                personPhoto
            )
        }

        /*  internal fun lastLoginUserInfo(): IGameLogin.UserInfo? {
              //判断google是否登录
              val account = GoogleSignIn.getLastSignedInAccount(app)
              return if (account != null && account.idToken != null && account.id != null) {
                  GameLoginGoogleImpl.toUserInfo(account)
              } else {
                  null
              }
          }*/

        fun logout(activity: Activity) {
            Identity.getSignInClient(activity).signOut()
        }
    }


    private lateinit var oneTapClient: SignInClient
    private lateinit var signInRequest: BeginSignInRequest
    private lateinit var activity: Activity


    override fun startLogin() {
        oneTapClient.beginSignIn(signInRequest)
            .addOnSuccessListener(activity) { result ->
                try {
                    callFragment.startIntentSenderForResult(
                        result.pendingIntent.intentSender, REQ_ONE_TAP,
                        null, 0, 0, 0, null
                    )
                } catch (e: IntentSender.SendIntentException) {
                    e.printStackTrace()
                    loginFail(e)
                }
            }
            .addOnFailureListener(activity) { e ->
                // No saved credentials found. Launch the One Tap sign-up flow, or
                // do nothing and continue presenting the signed-out UI.
                loginFail(e)
            }
            .addOnCanceledListener {
                loginCancel()
            }
    }

    override fun logOut() {
        logout(activity)
    }


    override fun onCreate(owner: LifecycleOwner) {
        super.onCreate(owner)
        activity = when (owner) {
            is Fragment -> {
                owner.requireActivity()
            }
            is Activity -> {
                owner
            }
            else -> {
                throw IllegalArgumentException("need a activity")
            }
        }
        oneTapClient = Identity.getSignInClient(activity)
        signInRequest = BeginSignInRequest.builder()
            .setPasswordRequestOptions(
                BeginSignInRequest.PasswordRequestOptions.builder()
                    .setSupported(true)
                    .build()
            )
            .setGoogleIdTokenRequestOptions(
                BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
                    .setSupported(true)
                    // Your server's client ID, not your Android client ID.
                    .setServerClientId(activity.getString(R.string.server_client_id))
                    // Only show accounts previously used to sign in.
                    //这里设置false，可以解决错误 16: Cannot find a matching credential.
                    .setFilterByAuthorizedAccounts(false)
                    .build()
            )
            // Automatically sign in when exactly one credential is retrieved.
            .setAutoSelectEnabled(true)
            .build()
    }

    override fun onActivityResultByFragment(requestCode: Int, resultCode: Int, data: Intent?) {
        when (requestCode) {
            REQ_ONE_TAP -> {
                try {
                    val credential = oneTapClient.getSignInCredentialFromIntent(data)
                    val idToken = credential.googleIdToken
                    val username = credential.id
                    val password = credential.password
                    if (idToken != null) {
                        loginSuccess(credential)
                    } else {
                        loginCancel()
                    }
                    /*    when {
                            idToken != null -> {
                                // Got an ID token from Google. Use it to authenticate
                                // with your backend.
                                //Log.d(TAG, "Got ID token.")
                            }
                            password != null -> {
                                // Got a saved username and password. Use them to authenticate
                                // with your backend.
                                //Log.d(TAG, "Got password.")
                            }
                            else -> {
                                // Shouldn't happen.
                                //Log.d(TAG, "No ID token or password!")
                            }
                        }*/
                } catch (e: ApiException) {
                    e.printStackTrace()
                    when (e.statusCode) {
                        CommonStatusCodes.CANCELED -> {
//                            Log.d(TAG, "One-tap dialog was closed.")
                            // Don't re-prompt the user.
                            loginCancel()
                        }
                        CommonStatusCodes.NETWORK_ERROR -> {
//                            Log.d(TAG, "One-tap encountered a network error.")
                            // Try again or just ignore.
                            loginFail(e)
                        }
                        else -> {
//                            Log.d(TAG, "Couldn't get credential from result." +
//                                    " (${e.localizedMessage})")
                            loginFail(e)
                        }
                    }
                }
            }
        }
    }

    private fun loginCancel() {
        listeners.forEach {
            it.onCancel(IGameLogin.LOGIN_GOOGLE)
        }
    }

    private fun loginFail(error: Throwable) {
        listeners.forEach {
            it.onError(error, IGameLogin.LOGIN_GOOGLE)
        }
    }

    private fun loginSuccess(account: SignInCredential) {
        val info = toUserInfo(account)
        listeners.forEach {
            it.onSuccess(info, IGameLogin.LOGIN_GOOGLE)
        }
    }
}